#ifndef __BUOLA_CV_CATTENTION_H__
#define __BUOLA_CV_CATTENTION_H__

#include <buola/image/cpyramid.h>

namespace buola { namespace cvi {

class CAttention
{
    typedef img::CPyramid<img::CImage_gray32f> tPyramid;

    static constexpr float mAlpha=1.5;
    static constexpr float mBeta=2.0;
    static constexpr float mIORRate=1.0;
    static constexpr int mHighScale=1;
    static constexpr int mLowScale=3;
    static constexpr int mNumPeaks=10;

public:
    enum EWeight
    {
        WEIGHT_INTENSITY,
        WEIGHT_ORIENTATION,
        WEIGHT_COLOR,
        WEIGHT_0,
        WEIGHT_45,
        WEIGHT_90,
        WEIGHT_135,
        WEIGHT_R,
        WEIGHT_G,
        WEIGHT_B,
        WEIGHT_Y,

        WEIGHT_COUNT
    };

    struct SPeak
    {
        SPeak(float x,float y,float c,int s)
            :   mPos(x,y),mAltitude(c),mSize(s)
        {}

        CSize_i mPos;
        float mAltitude;      // Peak altitude
        float mSize;     // Peak size
    };

    CAttention();
    ~CAttention();

private:
    void CalcColourMaps(const img::CView_rgb8 &pSrc);
    void CalcOrientation(const img::CView_rgb8 &pL);

    void Normalize(const img::CMView_gray32f &pImage);
    void CSD(tPyramid &pSrc,tPyramid &pCSD);
    void MakeConspicuityMaps(tPyramid &pCSD,const img::CMView_gray32f &pConsp,bool pClear);

    void CalcSM_BU(const img::CView_rgb8 &pL);
    void CalcSM_TD(const img::CView_rgb8 &pL);

    void CombineSM(const img::CMView_gray32f &SM, const img::CView_gray32f &SM_BU, const img::CView_gray32f &SM_TD); //dynamic combination of the two saliency maps
        //Stochastic Winner-Take-All competition find peak and push into peaks
    float CSI(const img::CView_gray32f &smap);       //composite saliency indicator
    float MaxEnThr(const img::CView_gray32f &smap);  //maximum entropy threshold

    float mean_locmax(const img::CView_gray32f &image, float maximum, int xsize);

    SPeak FindMaxPeak(const img::CView_gray32f &smap);
    void IOR(const img::CMView_gray32f &pMap,const SPeak &pPeak,float pRate); //inhibition of return on last peak in peaks (one time-step)
    void FindPeaks(const img::CView_gray32f &smap, int nump);

public:
    void SetTDWeights(const std::vector<double> &pWeights)  {   mWeights=pWeights;  }
    const std::vector<double> &GetTDWeights()   {   return mWeights;    }

    void Update(const img::CView_rgb8 &pI);

    int GetPeakCount()      {   return mPeaks.size();   }
    const SPeak &GetPeak(int i) {   return mPeaks[i];   }
    img::CView_gray32f GetSaliencyMap() {   return mSM_BU;    }

private:
    img::CImage_gray32f mSM,mSM_BU,mSM_TD;

    tPyramid mTmpPyramid,mTmpCSD;

    //temporary maps
    img::CImage_gray32f mRed,mGreen,mBlue,mYellow; ///< color maps
    img::CImage_gray32f mIntensity;
    img::CImage_gray32f mIConsp;
    img::CImage_gray32f mOConsp;

    std::vector<double> mWeights; //top down weights
    float mConcentration;
    float mAttention;
    float mKoeff;
    std::vector<SPeak> mPeaks;
};

/*namespace cvi*/ } /*namespace buola*/ }

#endif
